﻿using System;
using System.Collections.Generic;

namespace InfiniteConvergentSeries
{
    public class Program
    {
        private static double CalculateSum(Delegate function, double precision)
        {
            double last;
            double current = 0;
            foreach (double number in function())
            {
                last = current;
                current += number;
                if (current - last < precision)
                {
                    return double.Parse(string.Format("{0:F2}", current));
                }
            }
            throw new ArgumentException("Could not find an answer with that precision.");
        }

        private delegate IEnumerable<double> Delegate();

        private static IEnumerable<double> Function1()
        {
            double result = 2;
            while (true)
            {
                result /= 2;
                yield return result;
            }
        }

        private static IEnumerable<double> Function2()
        {
            int denominator = 1;
            int index = 1;
            while (true)
            {
                yield return (1.0 / denominator);
                denominator *= (++index);
            }
        }

        private static IEnumerable<double> Function3()
        {
            yield return 1;
            double result = -1;
            while (true)
            {
                result /= -2;
                yield return result;
            }
        }

        public static void Main()
        {
            double precision = 0.01;
            Delegate function = new Delegate(Function1);
            Console.WriteLine(CalculateSum(function, precision));
            function = new Delegate(Function2);
            Console.WriteLine(CalculateSum(function, precision));
            function = new Delegate(Function3);
            Console.WriteLine(CalculateSum(function, precision));
        }
    }
}
